/**
 * 
 */
package edu.rit.checkers;

import java.text.DecimalFormat;

import edu.rit.pj.Comm;

/**
 * Use this class to run a suit of size up tests on the Checkers sequential
 * and parallel programs.
 * 
 * @author Ian Tewksbury (ict8574@rit.edu)
 */
public class CheckersTesting {
	private static DecimalFormat f1 = new DecimalFormat("0000000");
	private static DecimalFormat f2 = new DecimalFormat("000.000");
	
	/**
	 * The usage message for running this program
	 */
	public static final String USAGE =
		"usage: CheckersTesting " +
		"<startDepth> <increaseDepth> <maxTime> <maxTimePerDepth>\n" +
		"<startDepth> the start depth of the tree\n" +
		"<increaseDepth> the amount to increase the depth " +
			"of the tree by if time allows\n" +
		"<maxTime> the max time to run the search\n" +
		"<depthMaxTime> the max time to spend searching " +
			"each depth increase\n";

	/**
	 * Runs a sequential test and series of SMP tests on the Checkers problem
	 * and displays size up data results.
	 * 
	 * @param args
	 * 	args[0] <startDepth> the start depth of the tree
	 * 	args[1] <increaseDepth> the amount to increase the depth of the tree
	 *by if time allows
	 * 	args[2] <maxTime> the max time to run the search
	 * 	args[3] <maxTimePerDepth> the max time to spend searching
	 *each depth increase
	 *
	 * @throws Exception parallel stuff can throw Exceptions
	 */
	public static void main(String[] args) throws Exception {
		Comm.init(args);
		
		int[] parsedArgs = Helpers.parseArgs(args);
		
		if(parsedArgs != null) {
			//print titles
			String s = " NT     S1       S2       S3       S      " +
			"SzeUp     Effic\n";
			s += "---  -------  -------  -------  -------  " +
			"-------   ------";
			System.out.println(s);
			
			//run seq tests
			long seq_max = runSeqTests(parsedArgs);
			
			//run smp tests
			runSMPTests(parsedArgs, 1, seq_max);
			runSMPTests(parsedArgs, 2, seq_max);
			runSMPTests(parsedArgs, 3, seq_max);
			runSMPTests(parsedArgs, 4, seq_max);
			runSMPTests(parsedArgs, 5, seq_max);
			runSMPTests(parsedArgs, 6, seq_max);
			runSMPTests(parsedArgs, 7, seq_max);
			runSMPTests(parsedArgs, 8, seq_max);
		} else {
			System.out.println(USAGE);
		}
	}
	
	/**
	 * run a 3 sequential tests
	 * 
	 * @param args
	 * 	args[0] <startDepth> the start depth of the tree
	 * 	args[1] <increaseDepth> the amount to increase the depth of the tree
	 *by if time allows
	 * 	args[2] <maxTime> the max time to run the search
	 * 	args[3] <maxTimePerDepth> the max time to spend searching
	 * 
	 * @return the max tree size from the three sequential runs
	 * 
	 * @throws Exception parallel stuff can throw Exceptions
	 */
	private static long runSeqTests(int[] args) throws Exception {
		String s = "seq  ";
		long seq_1, seq_2, seq_3, seq_max;
		seq_1 = CheckersSeq.runSeqTest(args[0], args[1], args[2],
				args[3], false);
		System.gc();
		s += f1.format(seq_1) + "  ";
		seq_2 = CheckersSeq.runSeqTest(args[0], args[1], args[2],
				args[3], false);
		System.gc();
		s += f1.format(seq_2) + "  ";
		seq_3 = CheckersSeq.runSeqTest(args[0], args[1], args[2],
				args[3], false);
		System.gc();
		s += f1.format(seq_3) + "  ";
		seq_max = Helpers.max(seq_1,seq_2,seq_3);
		s += f1.format(seq_max);
		
		System.out.println(s);
		
		return seq_max;
	}
	
	/**
	 * Run three SMP tests based on the given parameters
	 * 
	 * @param args
	 * 	args[0] <startDepth> the start depth of the tree
	 * 	args[1] <increaseDepth> the amount to increase the depth of the tree
	 *by if time allows
	 * 	args[2] <maxTime> the max time to run the search
	 * 	args[3] <maxTimePerDepth> the max time to spend searching
	 * 
	 * @param numThreads the number of threads to run the SMP test with
	 * @param seq_max the max sequential tree size to use for calculating sizeup
	 * 
	 * @return the max tree size from the tree SMP tests run
	 * 
	 * @throws Exception parallel stuff can throw Exceptions
	 */
	private static long runSMPTests(int[] args, int numThreads,
			long seq_max) throws Exception {
			
			String s = "  " + numThreads + "  ";
			long smp_1, smp_2, smp_3, smp_max;
			double  smp_szeup, smp_eff;
			smp_1 = CheckersSmp.runSmpTest(args[0], args[1], args[2],
				args[3], false, numThreads);
			System.gc();
			s += f1.format(smp_1) + "  ";
			smp_2 = CheckersSmp.runSmpTest(args[0], args[1], args[2],
				args[3], false, numThreads);
			System.gc();
			s += f1.format(smp_2) + "  ";
			smp_3 = CheckersSmp.runSmpTest(args[0], args[1], args[2],
				args[3], false, numThreads);
			System.gc();
			s += f1.format(smp_3) + "  ";
			smp_max = Helpers.max(smp_1,smp_2,smp_3);
			s += f1.format(smp_max) + "  ";
			smp_szeup = (double)smp_max / (double)seq_max;
			s += f2.format(smp_szeup) + "  ";
			smp_eff = (double)smp_szeup / (double)numThreads;
			s += f2.format(smp_eff) + "  ";
			
			System.out.println(s);
			
			return smp_max;
		}
}
